package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

const (
	DefLogOut  = "/tmp/log/dahuavto.log"
	DefGpioOut = "call_notify"
)

type DahuaVTO struct {
	Id          string `json:"id"`
	IP          string `json:"ip"`
	Port        int    `json:"port"`
	UserID      string `json:"userid"`
	Name        string `json:"name"`
	Password    string `json:"password"`
	Error       string `json:"error"`
	IsConnected bool   `json:"isConnected"`
	GPIO        int    `json:"gpio"`
	BtnName     string `json:"btn_name"`
}

type Config struct {
	Listen   string      `json:"listen"`
	Username string      `json:"username"`
	Password string      `json:"password"`
	UserID   string      `json:"userid"`
	VTOs     []*DahuaVTO `json:"vtos"`
	GpioOut  string      `json:"gpio_out"`
	LogOut   string      `json:"log_out"`
	BafaKey  string      `json:"bafa_key"`
}

func LoadConfigFromUCI(path string) (*Config, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, fmt.Errorf("failed to open config file: %v", err)
	}
	defer file.Close()
	config := &Config{
		LogOut:  DefLogOut,
		GpioOut: DefGpioOut,
	}
	currentSection := ""
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if line == "" || strings.HasPrefix(line, "#") {
			continue
		}

		if strings.HasPrefix(line, "config ") {
			parts := strings.Fields(line)
			if len(parts) >= 3 {
				currentSection = parts[1] + "_" + parts[2]
			}
			continue
		}

		if strings.HasPrefix(line, "option ") {
			parts := strings.Fields(line)
			if len(parts) >= 3 {
				key := parts[1]
				value := strings.Join(parts[2:], " ")
				value = strings.Trim(value, `"'`)
				switch currentSection {
				case "dahuavto_'main'":
					switch key {
					case "listen":
						config.Listen = value
					case "username":
						config.Username = value
					case "password":
						config.Password = value
					case "userid":
						config.UserID = value
					case "gpio_out":
						config.GpioOut = value
					case "log_out":
						config.LogOut = value
					case "bafa_key":
						config.BafaKey = value
					}
				default:
					if strings.HasPrefix(currentSection, "dahuavto_device_") {
						vto := DahuaVTO{}
						deviceId := strings.TrimPrefix(currentSection, "dahuavto_device_")
						var existing *DahuaVTO
						for i, d := range config.VTOs {
							if d.Id == deviceId {
								existing = config.VTOs[i]
								break
							}
						}
						if existing == nil {
							config.VTOs = append(config.VTOs, &vto)
							existing = config.VTOs[len(config.VTOs)-1]
							existing.Id = deviceId
						}
						switch key {
						case "id":
							existing.Id = value
						case "ip":
							existing.IP = value
						case "port":
							existing.Port, _ = strconv.Atoi(value)
						case "userid":
							existing.UserID = value
						case "name":
							existing.Name = value
						case "password":
							existing.Password = value
						case "gpio":
							existing.GPIO, _ = strconv.Atoi(value)
						case "btn_name":
							existing.BtnName = value
						}
					}
				}
			}
		}
	}
	if err := scanner.Err(); err != nil {
		return nil, fmt.Errorf("error reading config file: %v", err)
	}
	return config, nil
}

func SaveConfigToUCI(config *Config, path string) error {
	_ = os.Rename(path, path+".bak")
	file, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, os.ModePerm)
	if err != nil {
		return fmt.Errorf("failed to create config file: %v", err)
	}
	defer file.Close()

	writer := bufio.NewWriter(file)

	// Write main section
	_, err = writer.WriteString("config dahuavto 'main'\n")
	if err != nil {
		return err
	}

	writeOption := func(writer *bufio.Writer, key, value string) error {
		_, err := writer.WriteString(fmt.Sprintf("    option %s '%s'\n", key, value))
		return err
	}

	// Always write all main options, even if empty
	err = writeOption(writer, "listen", config.Listen)
	if err != nil {
		return err
	}
	err = writeOption(writer, "username", config.Username)
	if err != nil {
		return err
	}
	err = writeOption(writer, "password", config.Password)
	if err != nil {
		return err
	}
	err = writeOption(writer, "userid", config.UserID)
	if err != nil {
		return err
	}
	err = writeOption(writer, "gpio_out", config.GpioOut)
	if err != nil {
		return err
	}
	err = writeOption(writer, "log_out", config.LogOut)
	if err != nil {
		return err
	}
	err = writeOption(writer, "bafa_key", config.BafaKey)
	if err != nil {
		return err
	}
	// Write device sections
	for _, vto := range config.VTOs {
		_, err = writer.WriteString(fmt.Sprintf("\nconfig dahuavto_device %s\n", vto.Id))
		if err != nil {
			return err
		}
		// Always write all device options, even if empty
		err = writeOption(writer, "ip", vto.IP)
		if err != nil {
			return err
		}
		err = writeOption(writer, "port", strconv.Itoa(vto.Port))
		if err != nil {
			return err
		}
		err = writeOption(writer, "userid", vto.UserID)
		if err != nil {
			return err
		}
		err = writeOption(writer, "name", vto.Name)
		if err != nil {
			return err
		}
		err = writeOption(writer, "password", vto.Password)
		if err != nil {
			return err
		}
		err = writeOption(writer, "gpio", strconv.Itoa(vto.GPIO))
		if err != nil {
			return err
		}
		err = writeOption(writer, "btn_name", vto.BtnName)
		if err != nil {
			return err
		}
	}
	return writer.Flush()
}
